﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.Mvc.Filters;
using System.Web.Mvc;
using Downplay.Gravity.Services;
using System.Web.Helpers;
using Downplay.Gravity.Models;

namespace Downplay.Gravity.Filters
{
    public class AjaxFilterProvider : FilterProvider, IActionFilter, IResultFilter
    {
        private IGravityService _gravityService;

        public static object AjaxFilterHttpContextKey = new object();
        public static string AjaxDataPrefix = "djax";

        public AjaxFilterProvider(IGravityService gravityService)
        {
            _gravityService = gravityService;
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {

        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }



        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            // Prevent call on partial view
            var viewResult = filterContext.Result as ViewResult;
            if (viewResult == null)
                return;

            var query = filterContext.HttpContext.Request.QueryString;
            var djaxOn = query[AjaxDataPrefix];
            if (!String.IsNullOrWhiteSpace(djaxOn) && djaxOn == "true")
            {
                // Temporary hack : due to partial renders (Html.RenderAction) we end up with unfortunate recursion
                //       query.Remove("djaxOn");

                if (filterContext.HttpContext.Items[AjaxFilterHttpContextKey] == null)
                {
                    var ajaxIntercept = new AjaxFilterContext();
                    filterContext.HttpContext.Items[AjaxFilterHttpContextKey] = ajaxIntercept;

                    // Reconstruct gravity data from submitted query values
                    var data = new GravityData();
                    foreach (var k in query.AllKeys)
                    {
                        var dataPrefix = AjaxDataPrefix+"Data";
                        if (
                            // Ignore djax="true" query
                            k != AjaxDataPrefix &&
                            k.StartsWith(dataPrefix))
                        {
                            data[k.Substring(dataPrefix.Length)] = query[k];
                        }
                    }

                    // Gravity service can perform action now
                    var result = _gravityService.HandleAction(data);

                    // Store result to capture update regions
                    ajaxIntercept.Result = result;
                }

            }
        
        }


        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            // Prevent call on partial view
            var viewResult = filterContext.Result as ViewResult;
            if (viewResult == null)
                return;

            // Ignore usual response; send JSON data with update regions from captured output
            var ajaxIntercept = filterContext.HttpContext.Items[AjaxFilterHttpContextKey] as AjaxFilterContext;
            if (ajaxIntercept != null)
            {
                var json = Json.Encode(ajaxIntercept.Response);
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.Write(json);
            }
        }

    }
}